﻿using System;
using System.Collections.Generic;

// 定义委托类型 - 成绩打印
public delegate bool GradePrint(Student s);

public class Student
{
    public string Name { get; set; }
    public string StudentId { get; set; }
    public Dictionary<string, double> Grades { get; set; }

    // 委托属性 - 成绩打印方法
    public GradePrint GP { set; get; }

    public Student(string name, string studentId)
    {
        Name = name;
        StudentId = studentId;
        Grades = new Dictionary<string, double>();
    }

    // 添加成绩
    public void AddGrade(string course, double grade)
    {
        Grades[course] = grade;
    }

    // 使用委托打印成绩
    public bool PrintGrade()
    {
        if (GP != null)
        {
            return GP(this);
        }
        else
        {
            Console.WriteLine("未设置成绩打印方法");
            return false;
        }
    }
}

public class GradeReport
{
    // 按学期排序打印
    public static bool GradeReportOrderByTerm(Student s)
    {
        Console.WriteLine($"=== 按学期排序成绩单 - {s.Name} ===");
        Console.WriteLine($"学号: {s.StudentId}");
        Console.WriteLine("课程名称\t成绩");
        Console.WriteLine("----------------------");

        foreach (var grade in s.Grades)
        {
            Console.WriteLine($"{grade.Key}\t\t{grade.Value:F1}");
        }

        double average = CalculateAverage(s);
        Console.WriteLine($"平均分: {average:F1}");
        Console.WriteLine("======================\n");
        return true;
    }

    // 按成绩高低排序打印
    public static bool GradeReportOrderByScore(Student s)
    {
        Console.WriteLine($"=== 按成绩高低排序 - {s.Name} ===");
        Console.WriteLine($"学号: {s.StudentId}");
        Console.WriteLine("课程名称\t成绩\t等级");
        Console.WriteLine("--------------------------");

        // 按成绩降序排序
        var sortedGrades = new List<KeyValuePair<string, double>>(s.Grades);
        sortedGrades.Sort((x, y) => y.Value.CompareTo(x.Value));

        foreach (var grade in sortedGrades)
        {
            string level = GetGradeLevel(grade.Value);
            Console.WriteLine($"{grade.Key}\t\t{grade.Value:F1}\t{level}");
        }

        double average = CalculateAverage(s);
        Console.WriteLine($"平均分: {average:F1}");
        Console.WriteLine("==========================\n");
        return true;
    }

    // 简洁格式打印
    public static bool GradeReportSimple(Student s)
    {
        Console.WriteLine($"学生: {s.Name}({s.StudentId})");
        Console.Write("成绩: ");

        foreach (var grade in s.Grades)
        {
            Console.Write($"{grade.Key}:{grade.Value:F1} ");
        }

        double average = CalculateAverage(s);
        Console.WriteLine($"| 平均: {average:F1}\n");
        return true;
    }

    // 计算平均分
    private static double CalculateAverage(Student s)
    {
        if (s.Grades.Count == 0) return 0;

        double sum = 0;
        foreach (var grade in s.Grades)
        {
            sum += grade.Value;
        }
        return sum / s.Grades.Count;
    }

    // 获取成绩等级
    private static string GetGradeLevel(double score)
    {
        if (score >= 90) return "优秀";
        if (score >= 80) return "良好";
        if (score >= 70) return "中等";
        if (score >= 60) return "及格";
        return "不及格";
    }
}

class Program
{
    static void Main()
    {
        // 创建学生
        Student student1 = new Student("张三", "2023001");
        Student student2 = new Student("李四", "2023002");
        Student student3 = new Student("王五", "2023003");

        // 添加成绩
        student1.AddGrade("数学", 85.5);
        student1.AddGrade("英语", 92.0);
        student1.AddGrade("物理", 78.5);

        student2.AddGrade("数学", 76.0);
        student2.AddGrade("英语", 88.5);
        student2.AddGrade("化学", 95.0);

        student3.AddGrade("数学", 92.5);
        student3.AddGrade("英语", 79.0);
        student3.AddGrade("生物", 87.0);

        // 测试不同的打印模板
        Console.WriteLine("=== 使用不同打印模板测试 ===\n");

        // 学生1使用按学期排序打印
        student1.GP = GradeReport.GradeReportOrderByTerm;
        Console.WriteLine("学生1 - 按学期排序:");
        student1.PrintGrade();

        // 学生2使用按成绩高低排序打印
        student2.GP = GradeReport.GradeReportOrderByScore;
        Console.WriteLine("学生2 - 按成绩高低排序:");
        student2.PrintGrade();

        // 学生3使用简洁格式打印
        student3.GP = GradeReport.GradeReportSimple;
        Console.WriteLine("学生3 - 简洁格式:");
        student3.PrintGrade();

        // 动态切换打印模板
        Console.WriteLine("=== 动态切换打印模板 ===\n");

        // 同一个学生使用不同的打印方式
        Student testStudent = new Student("测试学生", "2023999");
        testStudent.AddGrade("语文", 88.0);
        testStudent.AddGrade("数学", 76.5);
        testStudent.AddGrade("英语", 92.5);
        testStudent.AddGrade("历史", 81.0);

        // 使用简洁格式
        testStudent.GP = GradeReport.GradeReportSimple;
        testStudent.PrintGrade();

        // 切换到按成绩排序
        testStudent.GP = GradeReport.GradeReportOrderByScore;
        testStudent.PrintGrade();

        // 切换到按学期排序
        testStudent.GP = GradeReport.GradeReportOrderByTerm;
        testStudent.PrintGrade();

        // 测试委托为空的情况
        Console.WriteLine("=== 测试委托为空的情况 ===");
        Student emptyStudent = new Student("空学生", "2023000");
        emptyStudent.AddGrade("测试课程", 85.0);
        emptyStudent.PrintGrade();

        // 使用匿名方法作为打印委托
        Console.WriteLine("=== 使用匿名方法 ===");
        student1.GP = delegate (Student s)
        {
            Console.WriteLine($"*** 自定义打印 - {s.Name} ***");
            Console.WriteLine($"总课程数: {s.Grades.Count}");
            return true;
        };
        student1.PrintGrade();

        // 使用Lambda表达式
        Console.WriteLine("=== 使用Lambda表达式 ===");
        student1.GP = s =>
        {
            Console.WriteLine($"Lambda打印: {s.Name}的成绩单");
            return true;
        };
        student1.PrintGrade();
    }
}